#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>

void dirProcess(char * dirname, int tab_depth);
void dirProcessMatch(char * dirname, int tab_depth, char * match);

int main (int argc, char * argv[]) {
  char * dirname;
  dirname = ".";
  
  if (argc > 1) // if there are command line arguments,
    dirProcessMatch(dirname, 0, argv[1]); // use the first one as a matching term.
  else // if there are no arguments,
    dirProcess(dirname, 0); // run the normal function.
  
  return 0;
}

void dirProcess(char * dirname, int tab_depth) {
  /*   This function is designed to check each item within a certain directory.
   *   Long story short, if it's a directory, recurse on that one, if it's a 
   *   regular file, print the name and size, otherwise ignore it.
   */
  DIR 		* dirStream;
  struct dirent * dirEntry;
  
  if((dirStream = opendir(dirname)) == NULL) {
    perror("opendir");
    return;
  }
  
  while ((dirEntry = readdir(dirStream)) != NULL)
  {
    /* 	Handle each directory entry here.
     * 		- if entry is "." or "..", ignore
     *		- if entry is a symboic link, ignore
     *		- if entry is a directory, recurse
     *		- if entry is a file, print name and size
     */
    struct stat stats;
    char nextFile[1024];
    
    if (tab_depth == 0) {
      strcpy(nextFile, dirEntry->d_name);
    }
    else {
      strcpy(nextFile, dirname);
      strcat(nextFile, "/");
      strcat(nextFile, dirEntry->d_name);
    }
    
    if (stat(nextFile, &stats) != 0) {
      perror("stat");
      printf("Failed on:  '%s'.\n", dirEntry->d_name);
      return;
    }
    
    if (strcmp(dirEntry->d_name, ".")  == 0) continue;
    else if (strcmp(dirEntry->d_name, "..") == 0) continue;
    else if (S_ISDIR(stats.st_mode) != 0) {
      int t = 0;
      for (t=0; t<tab_depth; t++) printf("    ");
      printf("%s (subdirectory)\n", dirEntry->d_name);
      dirProcess(nextFile, tab_depth+1);
    }
    else if (S_ISREG(stats.st_mode) != 0) {
      int t = 0;
      for (t=0; t<tab_depth; t++) printf("    ");
      printf("%s (%d bytes)\n", dirEntry->d_name, (int)stats.st_size);
    }
    else continue;
  }
}






void dirProcessMatch(char * dirname, int tab_depth, char * match) {
  /*   This function is designed to check each item within a certain directory.
   *   Long story short, if it's a directory, recurse on that one, if it's a 
   *   regular file and it matches the search term, print the name and size, 
   *   otherwise ignore it.
   */
  
  DIR 		* dirStream;
  struct dirent * dirEntry;
  
  if((dirStream = opendir(dirname)) == NULL) {
    perror("opendir");
    return;
  }
  
  while ((dirEntry = readdir(dirStream)) != NULL)
    {
      /* 	Handle each directory entry here.
       * 		- if entry is "." or "..", ignore
       *		- if entry is a symboic link, ignore
       *		- if entry is a directory, recurse
       *		- if entry is a file, print name and size
       */
      struct stat stats;
      char nextFile[1024];
      
      if (tab_depth == 0) {
	strcpy(nextFile, dirEntry->d_name);
      }
      else {
	strcpy(nextFile, dirname);
	strcat(nextFile, "/");
	strcat(nextFile, dirEntry->d_name);
      }
      
      if (stat(nextFile, &stats) != 0) {
	perror("stat");
	printf("Failed on:  '%s'.\n", dirEntry->d_name);
	return;
      }
      
      if (strcmp(dirEntry->d_name, ".")  == 0) continue;
      else if (strcmp(dirEntry->d_name, "..") == 0) continue;
      else if (S_ISDIR(stats.st_mode) != 0) {
	
	int t = 0;
	for (t=0; t<tab_depth; t++) printf("    ");
	printf("%s (subdirectory)\n", dirEntry->d_name);
	dirProcessMatch(nextFile, tab_depth+1, match);
      }
      else if (S_ISREG(stats.st_mode) != 0) {
	if (strcmp(dirEntry->d_name, match)) continue;
	
	int t = 0;
	for (t=0; t<tab_depth; t++) printf("    ");
	printf("%s (%d bytes)\n", dirEntry->d_name, (int)stats.st_size);
      }
      else continue;
    }
}
